package com.tree.thread.pool;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @ClassName com.tree.thread
 * Description: 自定义线程池
 * <p>
 *     TODO：
 * 1. work count 工作数量、完成的线程数量ncompleted、激活的线程nactive
 * 2. keepalivetime
 * 3. threadFactory
 * 4. reject 策略
 * 5. coresize创建线程， > coresize --> queue,  >queuesize < max ， 创建
 *
 *
 * 问题：
 * 1. 当线程空闲时间达到keepAliveTime，该线程会退出，有两个疑问：1、线程为什么会空闲 2、线程为什么要退出
 * 2, 线程中断https://www.jianshu.com/p/e0ff2e420ab6
 * </p>
 * @Author tree
 * @Date 2019-10-31 21:32
 * @Version 1.0
 */
public class ThreadPool {

    private volatile int coreSize = 5;
    private volatile int maxSize = 100;
    private volatile int workerNum;
    private volatile int queueNum = 10;
    private final BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(queueNum);

    private Worker[] workers;

    public ThreadPool(int coreSize, int maxSize) {
        this.coreSize = coreSize;
        if(maxSize > 0) {
            this.maxSize = maxSize;
        }
        workers = new Worker[coreSize];
        for(int i=0; i < coreSize; i++){
            workers[i] = new Worker();
            workers[i].start();
        }
    }

    public void execute(Runnable task){
        try {
            System.out.println("执行：ThreadPool{" +
                    ", waiting task number (queue size) = "+workQueue.size()+"}");
            workQueue.put(task);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void destroy() throws InterruptedException {
        System.out.println("destroy...");
        for(int i=0; i < coreSize; i++){
            workers[i].stopWorker();
            workers[i] = null;
        }
        workQueue.clear();


    }

    @Override
    public String toString() {
        return "ThreadPool{" +
                "coreSize=" + coreSize +
                ", maxSize=" + maxSize +
                ", waiting task number (queue size) = "+workQueue.size()+"}";

//        return super.toString() +
//                "[" + rs +
//                ", pool size = " + nworkers +
//                ", active threads = " + nactive +
//                ", queued tasks = " + workQueue.size() +
//                ", completed tasks = " + ncompleted +
//                "]";
    }

    class Worker extends Thread {

        private String name;

        @Override
        public void run() {
            try{
                while (!isInterrupted()){
                    Runnable r  = workQueue.take();
                    if(r!=null){
                        System.out.println(Thread.currentThread().getName()+", 执行Worker ..."+r);
                        r.run();
                        //帮助GC
                        r = null;
                    }
                }
            }
            catch (Exception e){
                System.err.println("worker error:");
                System.err.println(e);
            }
        }

        public void stopWorker(){
            interrupt();
        }

    }



}

class ThreadPoolTest{

    public static void main(String[] args) throws InterruptedException {

        ThreadPool t  = new ThreadPool(3,10);
        System.out.println("开始"+t);
        for(int i = 0; i < 5; i++){
            t.execute(new MyTask("test_"+i));
        }

        //等待4s到线程执行完成
//        Thread.sleep(10000);
        t.destroy();
        System.out.println("结束"+t);
    }
}

class  MyTask implements Runnable{
    private String name;
    private Random random = new Random();

    public MyTask(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Random getRandom() {
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    @Override
    public void run() {
        try {
            int r = random.nextInt(1000)+2000;
            System.out.println("线程["+name+"] thread sleep "+r);
            Thread.sleep(r);
        } catch (InterruptedException e) {
            System.err.println("MyTask[ 线程: "+Thread.currentThread().getName()+" ] occurs sleep interrupt "+ Thread.currentThread().isInterrupted());
        }
        System.out.println("任务"+name+" 完成");


    }

    @Override
    public String toString() {
        return "MyTask{" +
                "name='" + name + '\'' +
                ", random=" + random+
                '}';
    }
}

/**
 * The default thread factory
 */
class MyThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    MyThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        namePrefix = "MyThreadFactory-pool-" +
                poolNumber.getAndIncrement() +
                "-thread-";
    }

    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0);
        if (t.isDaemon())
            t.setDaemon(false);
        if (t.getPriority() != Thread.NORM_PRIORITY)
            t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}

